import { ipcMain, BrowserWindow, dialog } from 'electron'
import FFmpeg, { FFmpegOptions } from './utils/ffmpeg'
import fs from 'fs'
import path from 'path'

/**
 * IPC主进程事件管理类
 * 用于集中注册和处理所有从渲染进程发送到主进程的IPC事件
 */
class IpcMainHandler {
  private isDialogOpen = false

  /**
   * 初始化并注册所有IPC事件监听器
   */
  public initialize(): void {
    this.registerAppControlEvents()
    this.registerFileOperationEvents()
    this.registerDataFetchEvents()
    this.registerVideoConversionEvents()
    // 可以根据需要添加更多事件分组
  }

  /**
   * 注册与应用程序控制相关的事件
   */
  private registerAppControlEvents(): void {
    // 添加窗口控制的处理程序
    ipcMain.on('window-control', (_, command) => {
      const win = BrowserWindow.getFocusedWindow()
      if (!win) return

      switch (command) {
        case 'minimize':
          win.minimize()
          break
        case 'maximize':
          if (win.isMaximized()) {
            win.unmaximize()
          } else {
            win.maximize()
          }
          break
        case 'close':
          win.close()
          break
      }
    })
  }

  /**
   * 注册与文件操作相关的事件
   */
  private registerFileOperationEvents(): void {
    // 选择文件路径
    ipcMain.handle('file:selectDirectory', async () => {
      try {
        const win = BrowserWindow.getFocusedWindow()
        if (!win) {
          throw new Error('无法获取当前窗口')
        }

        // 保存当前窗口状态
        const wasMinimized = win.isMinimized()
        const wasMaximized = win.isMaximized()

        // 禁用窗口交互
        this.isDialogOpen = true
        win.setEnabled(false)

        const result = await dialog.showOpenDialog({
          properties: ['openDirectory']
        })

        // 恢复窗口交互
        win.setEnabled(true)
        this.isDialogOpen = false

        // 恢复窗口状态
        if (wasMinimized) {
          win.minimize()
        } else if (wasMaximized) {
          win.maximize()
        } else {
          win.restore()
        }

        // 确保窗口获得焦点
        win.focus()

        if (!result.canceled && result.filePaths.length > 0) {
          return {
            success: true,
            path: result.filePaths[0]
          }
        } else {
          return {
            success: false,
            error: '用户取消选择'
          }
        }
      } catch (error) {
        // 确保在出错时也恢复窗口交互
        const win = BrowserWindow.getFocusedWindow()
        if (win) {
          win.setEnabled(true)
          win.focus()
        }
        this.isDialogOpen = false
        return {
          success: false,
          error: error instanceof Error ? error.message : '未知错误'
        }
      }
    })

    // 文件选择事件
    ipcMain.handle('file:selectFile', async (_event, options) => {
      try {
        const win = BrowserWindow.getFocusedWindow()
        if (!win) {
          throw new Error('无法获取当前窗口')
        }

        // 保存当前窗口状态
        const wasMinimized = win.isMinimized()
        const wasMaximized = win.isMaximized()

        // 禁用窗口交互
        this.isDialogOpen = true
        win.setEnabled(false)

        const result = await dialog.showOpenDialog({
          properties: ['openFile', 'multiSelections'],
          filters: [
            {
              name: 'Videos',
              extensions: options.accept.split(',').map((ext) => ext.replace('.', ''))
            }
          ]
        })

        // 恢复窗口交互
        win.setEnabled(true)
        this.isDialogOpen = false

        // 恢复窗口状态
        if (wasMinimized) {
          win.minimize()
        } else if (wasMaximized) {
          win.maximize()
        } else {
          win.restore()
        }

        // 确保窗口获得焦点
        win.focus()

        if (!result.canceled && result.filePaths.length > 0) {
          return {
            success: true,
            filePaths: result.filePaths
          }
        } else {
          return {
            success: false,
            error: '用户取消选择'
          }
        }
      } catch (error) {
        // 确保在出错时也恢复窗口交互
        const win = BrowserWindow.getFocusedWindow()
        if (win) {
          win.setEnabled(true)
          win.focus()
        }
        this.isDialogOpen = false
        return {
          success: false,
          error: error instanceof Error ? error.message : '未知错误'
        }
      }
    })

    // 添加文件验证事件
    ipcMain.handle('file:validateFiles', async (_event, options) => {
      try {
        const { filePaths, accept } = options
        const acceptExtensions = accept.split(',').map((ext) => ext.replace('.', '').toLowerCase())

        // 验证文件类型
        const validFilePaths = filePaths.filter((path) => {
          const extension = path.split('.').pop()?.toLowerCase()
          return extension && acceptExtensions.includes(extension)
        })

        // 检查文件是否存在
        const existingFilePaths = await Promise.all(
          validFilePaths.map(async (path) => {
            try {
              const stats = await fs.promises.stat(path)
              return stats.isFile() ? path : null
            } catch (error) {
              return error
            }
          })
        )

        // 过滤掉不存在的文件
        const finalFilePaths = existingFilePaths.filter((path) => path !== null)

        if (finalFilePaths.length === 0) {
          return {
            success: false,
            error: '没有有效的文件'
          }
        }

        return {
          success: true,
          filePaths: finalFilePaths
        }
      } catch (error) {
        return {
          success: false,
          error: error instanceof Error ? error.message : '未知错误'
        }
      }
    })
  }

  /**
   * 注册与数据获取相关的事件
   */
  private registerDataFetchEvents(): void {
    // 获取系统信息示例
    ipcMain.handle('data:getSystemInfo', async () => {
      try {
        // 在这里实现获取系统信息的逻辑
        return {
          success: true,
          data: {
            platform: process.platform,
            arch: process.arch,
            nodeVersion: process.version
          }
        }
      } catch (error) {
        console.error('获取系统信息失败:', error)
        return { success: false, error: (error as Error).message }
      }
    })
  }

  /**
   * 注册与视频转换相关的事件
   */
  private registerVideoConversionEvents(): void {
    // 存储正在进行的转换任务
    const activeConversions: Map<string, FFmpeg> = new Map()

    ipcMain.handle('video:convert', async (_event, options: FFmpegOptions | FFmpegOptions[]) => {
      try {
        const win = BrowserWindow.getFocusedWindow()
        if (!win) {
          throw new Error('无法获取当前窗口')
        }
        // 判断是否是数组（多文件转换）
        if (Array.isArray(options)) {
          const results = await Promise.all(
            options.map(async (opt) => {
              const ffmpeg = new FFmpeg(opt, win)
              activeConversions.set(opt.inputPath, ffmpeg)
              await ffmpeg.process()
              activeConversions.delete(opt.inputPath)
              return { success: true, inputPath: opt.inputPath }
            })
          )
          return { success: true, results }
        } else {
          // 单文件转换
          const ffmpeg = new FFmpeg(options, win)
          activeConversions.set(options.inputPath, ffmpeg)
          await ffmpeg.process()
          activeConversions.delete(options.inputPath)
          return { success: true }
        }
      } catch (error) {
        console.error('视频转换失败:', error)
        return { success: false, error: error instanceof Error ? error.message : '未知错误' }
      }
    })

    // 添加取消转换事件处理
    ipcMain.handle('video:cancelConvert', async (_event, inputPath: string) => {
      try {
        const win = BrowserWindow.getFocusedWindow()
        if (!win) {
          throw new Error('无法获取当前窗口')
        }
        const ffmpeg = activeConversions.get(inputPath)
        if (!ffmpeg) {
          throw new Error('未找到对应的转换任务')
        }
        const removePath = ffmpeg.cancel()

        // 尝试多次删除，避免文件被占用
        const maxRetries = 5
        const retryDelay = 500 // 500ms

        let retries = 0
        while (retries < maxRetries) {
          try {
            await fs.promises.unlink(path.join(removePath))
            break // 删除成功，跳出循环
          } catch (error: any) {
            if (error.code === 'EBUSY') {
              retries++
              await new Promise((resolve) => setTimeout(resolve, retryDelay)) // 等待一段时间后重试
            } else {
              throw error // 其他错误直接抛出
            }
          }
        }

        activeConversions.delete(inputPath)
        return { success: true }
      } catch (error) {
        console.error('取消转换失败:', error)
        return { success: false, error: error instanceof Error ? error.message : '未知错误' }
      }
    })
  }

  /**
   * 移除所有注册的IPC事件监听器
   */
  public removeAllListeners(): void {
    ipcMain.removeAllListeners()
  }
}

// 导出单例实例
export const ipcMainHandler = new IpcMainHandler()
